package com.qianfeng.smartdevices.controller.advice;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianfeng.smartdevices.annotations.AopLogAnnotation;
import com.qianfeng.smartdevices.dto.R;
import com.qianfeng.smartdevices.dto.ResultCode;
import com.qianfeng.smartdevices.exceptions.MybaseException;
import com.qianfeng.smartdevices.pojo.BaseUser;
import com.qianfeng.smartdevices.pojo.LogData;
import com.qianfeng.smartdevices.service.LogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


@ControllerAdvice
@ResponseBody
@Aspect
public class MyControllerAdvice {

    private ObjectMapper objectMapper;

    private LogService logService;
    private ApplicationContext context;
    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Autowired
    public void setLogService(LogService logService) {
        this.logService = logService;
    }

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @ExceptionHandler(MybaseException.class)
    public R processMyBaseException(MybaseException exception) {
        String message = exception.getMessage();
        int code = exception.getCode();
        return R.SetError(null, message, code);
    }

    /**
     * 处理未知异常的
     * @param exception
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R processMyBaseException(Exception exception) {
        exception.printStackTrace();
        return R.SetError(null, "请检查网络", ResultCode.ERROR);
    }
    @Pointcut("execution(* com.qianfeng.smartdevices.controller.*.*(..))")
    public void qierudian() {

    }
    @Around("qierudian()")
    public Object processAround(ProceedingJoinPoint joinPoint) throws Throwable{
        try {
            LogData logData = new LogData();
            Map parmaMap = new HashMap();

            Object[] args = joinPoint.getArgs();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            String[] parameterNames = signature.getParameterNames();
            if (parameterNames != null) {
                for (int i = 0; i<parameterNames.length;i++) {
                    String parameterName = parameterNames[i];
                    Object arg = args[i];
                    parmaMap.put(parameterName,arg);
                }
            }
            String parmaJson = objectMapper.writeValueAsString(parmaMap);
            logData.setParams(parmaJson);
            Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            if (principal != null) {
                String username = ((BaseUser) principal).getUsername();
                logData.setUser(username);
            }
            Object proceed = joinPoint.proceed();
            if (proceed instanceof R) {
                Object result = ((R) proceed).getResult();

                logData.setResult(objectMapper.writeValueAsString(result));
                logData.setMsg(((R) proceed).getMsg());
                logData.setCode(((R) proceed).getCode());
            }
            Method method = signature.getMethod();
            AopLogAnnotation aopLogAnnotation = method.getAnnotation(AopLogAnnotation.class);
            if (aopLogAnnotation!= null ) {
                String value = aopLogAnnotation.value();
                logData.setCaozuo(value);
            }
            System.err.println("这是收集到的数据" + logData);
            logService.addLogData(logData);


            return proceed;

        } catch (Throwable e) {
            e.printStackTrace();
            throw e;
        }
    }

}
